package com.xiaoma.tpo.webservice;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xiaoma.tpo.dao.ClsClassDao;
import com.xiaoma.tpo.dao.TimelineDao;
import com.xiaoma.tpo.domain.BonusSignAchievement;
import com.xiaoma.tpo.domain.BonusSignRule;
import com.xiaoma.tpo.domain.BonusTask;
import com.xiaoma.tpo.domain.BonusTaskRecord;
import com.xiaoma.tpo.domain.BonusTaskRule;
import com.xiaoma.tpo.domain.BonusUserSign;
import com.xiaoma.tpo.domain.ClsClass;
import com.xiaoma.tpo.domain.Timeline;
import com.xiaoma.tpo.domain.User;
import com.xiaoma.tpo.dto.BonusBoard;
import com.xiaoma.tpo.dto.BonusTaskDto;
import com.xiaoma.tpo.resource.TPOConstants;
import com.xiaoma.tpo.resource.TimelineContent;
import com.xiaoma.tpo.service.BonusPointService;
import com.xiaoma.tpo.service.UserService;
import com.xiaoma.tpo.utils.TPOUtils;

@Controller
@RequestMapping("/service/bonus")
public class BonusPointWS {

    @Autowired
    private BonusPointService bonusPointService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private TimelineDao timelineDao;
    @Autowired
    private ClsClassDao classDao;
    
    @RequestMapping(value = "/sign", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> signIn(@RequestHeader String token) {
        Map<String, Object> result = new HashMap<String, Object>();
        User user = userService.findByToken(token);
        if(null == user) {
            result.put("status", -2);
            result.put("message", "invalid token");
            return result;
        }
        if (TPOUtils.isAnonymous(user)) {
            result.put("status", 0);
            result.put("message", "anonymous can't access");
            return result;
            
        }
        if (TPOUtils.over7days(new Date(), user.getLastVisit())) {//大于7天token失效
            result.put("status", -1);
            result.put("message", "token disabled over 7 days, please login");
            return result;
        }
        
        BonusUserSign bonusUserSign = bonusPointService.findLastSign(user.getId());// 获取最近一次的签到
        int point = 0;
        if (bonusUserSign == null) {// 第一次签到
            Map<String, Object> map = bonusPointService.getSignPoint(1);
            point = (Integer) map.get("point");
            saveUserSign(user.getId(),1,point);
            saveTimeline(user.getId(), TimelineContent.sign(1));
            // 保存成就
            BonusSignRule bonusSignRule = (BonusSignRule) map.get("bonusSignRule");
            saveBonusSignAchievement(user.getId(),bonusSignRule.getId());
            saveTimeline(user.getId(), TimelineContent.achievement(bonusSignRule.getTitle()));
            user.setBonusPoint(point + user.getBonusPoint());
            
        } else {// 多次签到
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            if (!formatter.format(calendar.getTime()).equals(formatter.format(bonusUserSign.getCreatedAt()))) {// 如果不是今天
                calendar.add(Calendar.DAY_OF_MONTH, -1);
                if (formatter.format(calendar.getTime()).equals(formatter.format(bonusUserSign.getCreatedAt()))) {// 如果昨天签到
                    Map<String, Object> map = bonusPointService.getSignPoint(bonusUserSign.getSignCount() + 1);
                    point = (Integer) map.get("point");
                    saveUserSign(user.getId(),bonusUserSign.getSignCount() + 1, point);
                    saveTimeline(user.getId(), TimelineContent.sign(bonusUserSign.getSignCount() + 1));
                    
                    // 验证是否满足某种成就
                    BonusSignRule bonusSignRule = (BonusSignRule) map.get("bonusSignRule");
                    List<BonusSignRule> rules = (List<BonusSignRule>) map.get("rules");
                    BonusSignAchievement entity = new BonusSignAchievement();
                    entity.setUserId(user.getId());
                    BonusSignAchievement bonusSignAchievement = bonusPointService.findSignAchievements(entity).get(0);
                    if ((bonusSignAchievement.getBonusSignRuleId() != rules.get(rules.size() - 1).getId()) && (bonusSignAchievement.getBonusSignRuleId() < bonusSignRule.getId())) {// 如果没达到最高成就并且比已存在的成就高
                        bonusSignAchievement.setBonusSignRuleId(bonusSignRule.getId());
                        bonusPointService.update(bonusSignAchievement);
                        saveTimeline(user.getId(), TimelineContent.achievement(bonusSignRule.getTitle()));
                    }

                } else {// 没连续签到
                    Map<String, Object> map = bonusPointService.getSignPoint(1);
                    point = (Integer) map.get("point");
                    saveUserSign(user.getId(),1,point);
                    saveTimeline(user.getId(), TimelineContent.sign(1));

                    BonusSignRule bonusSignRule = (BonusSignRule) map.get("bonusSignRule");
                    List<BonusSignRule> rules = (List<BonusSignRule>) map.get("rules");
                    BonusSignAchievement entity = new BonusSignAchievement();
                    entity.setUserId(user.getId());
                    BonusSignAchievement bonusSignAchievement = bonusPointService.findSignAchievements(entity).get(0);
                    if (bonusSignAchievement.getBonusSignRuleId() != rules.get(rules.size() - 1).getId()) {// 没到最高成就
                        bonusSignAchievement.setBonusSignRuleId(bonusSignRule.getId());
                        bonusPointService.update(bonusSignAchievement);
                        saveTimeline(user.getId(), TimelineContent.achievement(bonusSignRule.getTitle()));
                    }

                }
                user.setBonusPoint(point + user.getBonusPoint());
            }
        }
        userService.updateVisitTime(user);
        result.put("status", 1);
        return result;
    }
    
    @RequestMapping(value = "/task", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> task(@RequestParam String dateStr) {
        Map<String, Object> result = new HashMap<String, Object>();
        List<BonusTask> dayTasks = new ArrayList<BonusTask>();
        List<BonusTask> weekTasks = new ArrayList<BonusTask>();
        List<BonusTask> fixedTasks = new ArrayList<BonusTask>();
        List<BonusTask> classTasks = new ArrayList<BonusTask>();
        try {
            Date specificDay = TPOUtils.parseDateFromString(dateStr);
          //天任务
            if (TPOUtils.compareDate(specificDay, new Date()) == 0) {//指定日期
                dayTasks = bonusPointService.getTasksByType(TPOConstants.TASK_DAY);
                Date[] day = TPOUtils.getSpecificDateRange(1, specificDay);
                if (dayTasks.size() == 0) {
                    List<BonusTaskRule> dayRules = bonusPointService.findRulesRandom(TPOConstants.TASK_DAY, 2);
                    for (BonusTaskRule item: dayRules) {
                        BonusTask task = new BonusTask();
                        task.setTimeType(item.getTimeType());
                        task.setTitle(item.getTitle());
                        task.setImg(item.getImg());
                        task.setDescription(item.getDescription());
                        task.setCategory(item.getCategory());
                        task.setNumber(item.getNumber());
                        task.setBonusPoint(item.getBonusPoint());
                        task.setStart(day[0]);
                        task.setEnd(day[1]);
                        task.setTaskRuleId(item.getId());
                        int id = bonusPointService.saveBonusTask(task);
                        task.setId(id);
                        dayTasks.add(task);
                    }
                }
            }
            
          //周任务
            Date[] week = TPOUtils.getSpecificDateRange(2, new Date());
            if (TPOUtils.compareDate(specificDay, week[1]) < 0 && TPOUtils.compareDate(specificDay, week[0]) >= 0) {//指定日期不能超过这周
                weekTasks = bonusPointService.getTasksByType(TPOConstants.TASK_WEEK);
                if (weekTasks.size() == 0) {
                    List<BonusTaskRule> weekRules = bonusPointService.findRulesRandom(TPOConstants.TASK_WEEK, 2);
                    for (BonusTaskRule item: weekRules) {
                        BonusTask task = new BonusTask();
                        task.setTimeType(item.getTimeType());
                        task.setTitle(item.getTitle());
                        task.setImg(item.getImg());
                        task.setDescription(item.getDescription());
                        task.setCategory(item.getCategory());
                        task.setNumber(item.getNumber());
                        task.setBonusPoint(item.getBonusPoint());
                        task.setStart(week[0]);
                        task.setEnd(week[1]);
                        task.setTaskRuleId(item.getId());
                        int id = bonusPointService.saveBonusTask(task);
                        task.setId(id);
                        weekTasks.add(task);
                    }
                }
            }
            
            //固定任务
            List<BonusTaskRule> fixedRules = bonusPointService.findRules(TPOConstants.TASK_FIXED);
            fixedTasks = new ArrayList<BonusTask>(fixedRules.size());
            for (BonusTaskRule item : fixedRules) {
                BonusTask task = bonusPointService.getFixedTasks(item.getId());
                if (task == null) {
                    task = new BonusTask();
                    task.setTimeType(item.getTimeType());
                    task.setTitle(item.getTitle());
                    task.setImg(item.getImg());
                    task.setDescription(item.getDescription());
                    task.setCategory(item.getCategory());
                    task.setNumber(item.getNumber());
                    task.setBonusPoint(item.getBonusPoint());
                    task.setTaskRuleId(item.getId());
                    task.setStart(TPOUtils.getExpiredDate());
                    task.setEnd(TPOUtils.getMaxDate());
                    int id = bonusPointService.saveBonusTask(task);
                    task.setId(id);
                }
                fixedTasks.add(task);
            }
            
            //班任务,每天一次
            if (TPOUtils.compareDate(specificDay, new Date()) == 0) {
                classTasks = bonusPointService.getTasksByType(TPOConstants.TASK_CLASS);
                if (classTasks.size() == 0) {
                    List<ClsClass> classes = classDao.findAll();
                    List<BonusTaskRule> classRules = bonusPointService.findRulesRandom(TPOConstants.TASK_CLASS, classes.size());
                    Date[] day = TPOUtils.getSpecificDateRange(1, specificDay);
                    for (int i = 0; i < classRules.size(); i++) {
                        BonusTask task = new BonusTask();
                        task.setTimeType(classRules.get(i).getTimeType());
                        task.setTitle(classRules.get(i).getTitle());
                        task.setImg(classRules.get(i).getImg());
                        task.setDescription(classRules.get(i).getDescription());
                        task.setCategory(classRules.get(i).getCategory());
                        task.setNumber(classRules.get(i).getNumber());
                        task.setBonusPoint(classRules.get(i).getBonusPoint());
                        task.setStart(day[0]);
                        task.setEnd(day[1]);
                        task.setTaskRuleId(classRules.get(i).getId());
                        task.setClassId(classes.get(i).getId());
                        int id = bonusPointService.saveBonusTask(task);
                        task.setId(id);
                        classTasks.add(task);
                    }
                }
            }
            
            result.put("dayTasks", dayTasks);
            result.put("weekTasks", weekTasks);
            result.put("fixedTasks", fixedTasks);
            result.put("classTasks", classTasks);
        } catch (ParseException e) {
            result.put("status", 0);
            result.put("message", e);
            e.printStackTrace();//TODO: TO BE CONTINUE...
        }
        
        return result;
    }
    
    @RequestMapping(value = "/task", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> saveTask(@RequestHeader String token, @RequestBody BonusTaskDto taskDto) {
        Map<String, Object> result = new HashMap<String, Object>();
        User user = userService.findByToken(token);
        if(null == user) {
            result.put("status", -2);
            result.put("message", "invalid token");
            return result;
        }
        if (TPOUtils.isAnonymous(user)) {
            result.put("status", 0);
            result.put("message", "anonymous can't access");
            return result;
            
        }
        if (TPOUtils.over7days(new Date(), user.getLastVisit())) {//大于7天token失效
            result.put("status", -1);
            result.put("message", "token disabled over 7 days, please login");
            return result;
        }
        List<Integer> taskIds = taskDto.getTaskIds();
        Date now = new Date();
        for (Integer taskId: taskIds) {
            BonusTask task = bonusPointService.findTaskById(taskId);
            if (task != null) {
                if (task.getTimeType() == TPOConstants.TASK_FIXED) {
                    saveBonusTaskRecord(task, user);
                } else {
                    if (task.getStart().compareTo(now) <= 0 && task.getEnd().compareTo(now) > 0) {//判断是否在时间范围内
                        saveBonusTaskRecord(task, user);
                    }
                }
            }
        }
        
        userService.updateVisitTime(user);
        result.put("status", 1);
        return result;
    }
    
//    @RequestMapping(value = "/achievement", method = RequestMethod.GET)
//    @ResponseBody
//    public Map<String, Object> achievement(@RequestHeader String token) {
//        Map<String, Object> result = new HashMap<String, Object>();
//        User user = userService.findByToken(token);
//        if(null == user) {
//            result.put("status", -2);
//            result.put("message", "invalid token");
//            return result;
//        }
//        if (TPOUtils.isAnonymous(user)) {
//            result.put("status", 0);
//            result.put("message", "anonymous can't access");
//            return result;
//            
//        }
//        if (TPOUtils.over7days(new Date(), user.getLastVisit())) {//大于7天token失效
//            result.put("status", -1);
//            result.put("message", "token disabled over 7 days, please login");
//            return result;
//        }
//        result.put("achievement", bonusPointService.findAchievementByUserId(user.getId()));
//        userService.updateVisitTime(user);
//        return result;
//    }
    @RequestMapping(value = "/board", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> bonusBoard(@RequestHeader String token) {
        Map<String, Object> result = new HashMap<String, Object>();
        User user = userService.findByToken(token);
        if (null == user) {
            result.put("status", -2);
            result.put("message", "invalid token");
            return result;
        }
        if (TPOUtils.isAnonymous(user)) {
            result.put("status", 0);
            result.put("message", "anonymous can't access");
            return result;

        }
        if (TPOUtils.over7days(new Date(), user.getLastVisit())) {// 大于7天token失效
            result.put("status", -1);
            result.put("message", "token disabled over 7 days, please login");
            return result;
        }
        List<BonusBoard> signList = bonusPointService.findUserSignAchievements(user.getId());
        List<BonusBoard> classAchievements = bonusPointService.findClassAchievements(user.getId());
        List<BonusBoard> taskAchievements = bonusPointService.findTaskAchievements(user.getId());
        List<BonusBoard> list = new ArrayList<BonusBoard>(signList.size() + classAchievements.size() + taskAchievements.size());
        list.addAll(signList);
        list.addAll(classAchievements);
        list.addAll(taskAchievements);
        userService.updateVisitTime(user);
        result.put("status", 1);
        result.put("list", list);
        return result;
    }
    
    
    //private method
    private void saveUserSign(int userId, int signCount, int bonusPoint) {
        BonusUserSign bonusUserSign = new BonusUserSign();
        bonusUserSign.setUserId(userId);
        bonusUserSign.setSignCount(signCount);
        bonusUserSign.setBonusPoint(bonusPoint);
        bonusUserSign.setCreatedAt(new Date());
        bonusPointService.save(bonusUserSign);
    }
    private void saveBonusSignAchievement(int userId, int ruleId) {
        BonusSignAchievement bonusSignAchievement = new BonusSignAchievement();
        bonusSignAchievement.setUserId(userId);
        bonusSignAchievement.setBonusSignRuleId(ruleId);
        bonusSignAchievement.setCreatedAt(new Date());
        bonusPointService.save(bonusSignAchievement);
    }
    private void saveBonusTaskRecord(BonusTask task, User user) {
        BonusTaskRecord entity = new BonusTaskRecord();
        entity.setTaskId(task.getId());
        entity.setUserId(user.getId());
        List<BonusTaskRecord> bonusRecords = bonusPointService.findByColumn(entity);
        if (bonusRecords.size() == 0) {
            BonusTaskRecord bonusTaskRecord = new BonusTaskRecord();
            bonusTaskRecord.setCreatedAt(new Date());
            bonusTaskRecord.setTaskId(task.getId());
            bonusTaskRecord.setUserId(user.getId());
            bonusPointService.save(bonusTaskRecord);
            saveTimeline(user.getId(), TimelineContent.task(task.getTitle()));
            user.setBonusPoint(user.getBonusPoint() + task.getBonusPoint());//用户加积分
        }
    }
    
    private void saveTimeline(int userId, String content) {
        Timeline tl = new Timeline();
        tl.setContent(content);
        tl.setUserId(userId);
        tl.setCreatedAt(new Date());
        timelineDao.insert(tl);
    }
    public static void main(String[] args) {
        List<String> a = new ArrayList<String>();
        a.add("a");
        a.add("b");
        a.add("c");
        List<String> b = new ArrayList<String>();
        b.add("d");
        b.add("e");
        b.add("f");
        List<String> c = new ArrayList<String>(a.size() + b.size());
        c.addAll(a);
        c.addAll(b);
        System.out.println(c.size());
        for (String s : c) {
            System.out.println(s);
        }
    }
}
